package de.jabc.sib.bio.ebi;

import de.metaframe.jabc.framework.execution.ExecutionEnvironment;
import de.metaframe.jabc.framework.sib.DocType;
import de.metaframe.jabc.framework.sib.SIB;
import de.metaframe.jabc.framework.sib.SIBMetaInfo;
import de.metaframe.jabc.framework.sib.SIBUtilities;
import de.metaframe.jabc.framework.sib.annotation.SIBClassLoader;
import de.metaframe.jabc.framework.sibgraph.model.SIBGraphModel;
import de.metaframe.jabc.sib.CodeGeneratorBlock;
import de.metaframe.jabc.sib.Executable;
import de.metaframe.jabc.sib.Generatable;
import de.metaframe.jabc.sib.LocalCheck;

/**
 * This class provides a skeleton implementation for the SIBs in this library.
 * 
 * @author Benjamin Bentmann, anna-lena
 * @version $Revision: 2576 $ $Date: 2008-01-13 12:01:43 +0100 (Sun, 13 Jan 2008) $
 */
@SIBClassLoader
public abstract class AbstractSIB implements SIBMetaInfo, LocalCheck,
		Executable, CodeGeneratorBlock, Generatable {

	/**
	 * This class holds the icon cache instance. Keeping this instance in a
	 * separate class allows for thread-safe lazy initialization of the cache.
	 * Remember, we do not need icons when running in headless mode.
	 */
	protected static class Icons {

		/**
		 * The icon cache used to load icons for this SIB library.
		 */
		public static final IconCache INSTANCE =
				new IconCache(AbstractSIB.class);

	}

	/**
	 * @see de.metaframe.jabc.framework.sib.SIBMetaInfo#getIcon()
	 */
	public Object getIcon() {
		return Icons.INSTANCE.get("ebi");
	}
	
	/**
	 * This class holds the documentation instance. Keeping this instance in a
	 * separate class allows for thread-safe lazy initialization of the documentation.
	 * Remember, we do not need resource bundles when running in headless mode.
	 */
	protected static class Strings {

		/**
		 * The bundle used to load documentation strings for this SIB library.
		 */
		public static final Documentation INSTANCE =
				new Documentation(AbstractSIB.class);

	}

	/**
	 * @see de.metaframe.jabc.framework.sib.SIBMetaInfo#getDocumentation(DocType,
	 *      String)
	 */
	public String getDocumentation(DocType type, String param) {
		return Strings.INSTANCE.get(this, type, param);
	}

	/**
	 * @see de.metaframe.jabc.sib.Executable#trace(ExecutionEnvironment)
	 */
	public String trace(ExecutionEnvironment environment) {
		return execute(environment);
	}

	/**
	 * @see de.metaframe.jabc.sib.LocalCheck#type()
	 */
	public Object type() {
		return null;
	}

	/**
	 * @see de.metaframe.jabc.sib.LocalCheck#checkSIB(SIB)
	 */
	public void checkSIB(SIB sib) {
		SIBUtilities.execute(StandardCheck.MISSING_SOURCES.getKey(), sib);
		SIBUtilities.execute(StandardCheck.MISSING_TARGETS.getKey(), sib);
		SIBUtilities.execute(StandardCheck.MISSING_BRANCH_LABELS_CUSTOM_LVL
				.getKey(), sib, LCStatus.ERROR);
		SIBUtilities.execute(StandardCheck.UNASSIGNED_BRANCHES_CUSTOM_LVL
				.getKey(), sib, LCStatus.ERROR);
	}

	/**
	 * Checks whether the specified SIB parameter has been exported as a model
	 * parameter. Usually, model parameters should not be local-checked because
	 * their effective values are provided by a graph SIB.
	 * 
	 * @param sib
	 *            The SIB whose parameter is to check.
	 * @param field
	 *            The name of the SIB parameter to check.
	 * @return {@code true} if the specified SIB parameter is a model parameter,
	 *         {@code false} otherwise.
	 * @throws NullPointerException
	 *             If any method parameter is {@code null}
	 */
	protected boolean isModelParameter(SIB sib, String field) {
		SIBGraphModel model = sib.getCell().getModel();
		return model.getModelArguments().findParameter(field, sib) != null;
	}

}
